package com.dragon.modules.yuegou.client.wechat_mini.model;

import com.dragon.modules.yuegou.client.wechat_mini.common.MiniException;
import com.dragon.modules.yuegou.client.wechat_mini.request.SubscribeMessageRequest;
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 订阅消息模板
 * 
 * @author liuwu
 *
 */
public class Template {

	/**
	 * 公用模板ID
	 */
	private Integer tid;

	/**
	 * 添加至帐号下的模板 id，发送小程序订阅消息时所需
	 */
	private String priTmplId;

	/**
	 * 模版标题
	 */
	private String title;

	/**
	 * 模版内容
	 */
	private String content;

	/**
	 * 模板内容示例
	 */
	private String example;

	/**
	 * 模版类型，2 为一次性订阅，3 为长期订阅
	 */
	private Integer type;

	/**
	 * 模版所属类目 id
	 */
	private Integer categoryId;

	/**
	 * 模板关键词列表
	 */
	private List<Keyword> keywords;

	/**
	 * 关键词映射表，key为keyword.name, value为keyword.rule + keyword.tid
	 */
	@JsonIgnore
	private transient Map<String, String> keywordMap;

	public Template() {

	}

	public Template(PriTemplate priTemplate, TemplateTitle templateTitle) {
		this.priTmplId = priTemplate.getPriTmplId();
		this.title = priTemplate.getTitle();
		this.content = priTemplate.getContent();
		this.example = priTemplate.getExample();
		this.type = priTemplate.getType();

		this.tid = templateTitle.getTid();
		this.categoryId = templateTitle.getCategoryId();
	}

	/**
	 * 获取模版标题 id
	 * 
	 * @return 模版标题 id
	 */
	public Integer getTid() {
		return tid;
	}

	/**
	 * 设置模版标题 id
	 * 
	 * @param tid 模版标题 id
	 */
	public void setTid(Integer tid) {
		this.tid = tid;
	}

	/**
	 * 获取添加至帐号下的模板 id，发送小程序订阅消息时所需
	 * 
	 * @return 添加至帐号下的模板 id，发送小程序订阅消息时所需
	 */
	public String getPriTmplId() {
		return priTmplId;
	}

	/**
	 * 设置添加至帐号下的模板 id，发送小程序订阅消息时所需
	 * 
	 * @param priTmplId 添加至帐号下的模板 id，发送小程序订阅消息时所需
	 */
	public void setPriTmplId(String priTmplId) {
		this.priTmplId = priTmplId;
	}

	/**
	 * 获取模版标题
	 * 
	 * @return 模版标题
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * 设置模版标题
	 * 
	 * @param title 模版标题
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * 获取模版内容
	 * 
	 * @return 模版内容
	 */
	public String getContent() {
		return content;
	}

	/**
	 * 设置模版内容
	 * 
	 * @param content 模版内容
	 */
	public void setContent(String content) {
		this.content = content;
	}

	/**
	 * 获取模板内容示例
	 * 
	 * @return 模板内容示例
	 */
	public String getExample() {
		return example;
	}

	/**
	 * 设置模板内容示例
	 * 
	 * @param example 模板内容示例
	 */
	public void setExample(String example) {
		this.example = example;
	}

	/**
	 * 获取模版类型，2 为一次性订阅，3 为长期订阅
	 * 
	 * @return 模版类型，2 为一次性订阅，3 为长期订阅
	 */
	public Integer getType() {
		return type;
	}

	/**
	 * 设置模版类型，2 为一次性订阅，3 为长期订阅
	 * 
	 * @param type 模版类型，2 为一次性订阅，3 为长期订阅
	 */
	public void setType(Integer type) {
		this.type = type;
	}

	/**
	 * 获取模版所属类目 id
	 * 
	 * @return 模版所属类目 id
	 */
	public Integer getCategoryId() {
		return categoryId;
	}

	/**
	 * 设置模版所属类目 id
	 * 
	 * @param categoryId 模版所属类目 id
	 */
	public void setCategoryId(Integer categoryId) {
		this.categoryId = categoryId;
	}

	/**
	 * 获取模板关键词列表
	 * 
	 * @return 模板关键词列表
	 */
	public List<Keyword> getKeywords() {
		return keywords;
	}

	/**
	 * 设置模板关键词列表
	 * 
	 * @param keywords 模板关键词列表
	 */
	public void setKeywords(List<Keyword> keywords) {
		this.keywords = keywords;
	}

	/**
	 * 依据此模板，从要发送的订阅消息对象中构建一个订阅消息发送请求
	 * 
	 * @param message 订阅消息
	 * @return 订阅消息发送请求
	 */
	public SubscribeMessageRequest createRequest(SubscribeMessage message) {
		if (!Objects.equals(this.tid, message.getTid())) {
			throw new MiniException("此模板不能用于该订阅消息：" + message);
		}
		SubscribeMessageRequest request = new SubscribeMessageRequest();
		request.setToUser(message.getToUser());
		request.setPage(message.getPage());
		request.setTemplateId(this.priTmplId);
		Map<String, String> map = keywordMap();
		message.getData().forEach((kname, kvalue) -> {
			String key = map.get(kname);
			if (key == null) {
				throw new MiniException(String.format("消息模板[%s]中不存在参数[%s]，请确定配置了此参数", title, kname));
			}
			request.put(key, kvalue);
		});
		return request;
	}

	private Map<String, String> keywordMap() {
		if (this.keywordMap == null) {
			this.keywordMap = new HashMap<>();
			if (this.keywords != null) {
				for (Keyword keyword : keywords) {
					this.keywordMap.put(keyword.getName(), keyword.getRule() + keyword.getKid());
				}
			}
		}
		return keywordMap;
	}

	/**
	 * 获取本模板支持的关键词名称集合（指中文名）
	 * 
	 * @return 关键词名称集合
	 */
	public Set<String> supportedKeywordNames() {
		return new HashSet<>(keywordMap.keySet());
	}

	/**
	 * 获取本模板支持的关键词集合（指英文名，用于消息发送接口）
	 * 
	 * @return 关键词集合
	 */
	public Set<String> supportedKeywords() {
		return new HashSet<>(keywordMap.values());
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Template [");
		if (tid != null) {
			builder.append("tid=");
			builder.append(tid);
			builder.append(", ");
		}
		if (priTmplId != null) {
			builder.append("priTmplId=");
			builder.append(priTmplId);
			builder.append(", ");
		}
		if (title != null) {
			builder.append("title=");
			builder.append(title);
			builder.append(", ");
		}
		if (content != null) {
			builder.append("content=");
			builder.append(content);
			builder.append(", ");
		}
		if (example != null) {
			builder.append("example=");
			builder.append(example);
			builder.append(", ");
		}
		if (type != null) {
			builder.append("type=");
			builder.append(type);
			builder.append(", ");
		}
		if (categoryId != null) {
			builder.append("categoryId=");
			builder.append(categoryId);
			builder.append(", ");
		}
		if (keywords != null) {
			builder.append("keywords=");
			builder.append(keywords);
		}
		builder.append("]");
		return builder.toString();
	}

}
